package cn.darkhorse.ticket.service.impl;

import cn.darkhorse.exception.ServiceException;
import cn.darkhorse.ticket.pojo.MesCodeRules;
import cn.darkhorse.ticket.mapper.MesCodeRulesMapper;
import cn.darkhorse.ticket.service.MesCodeRulesService;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <p>
 * 业务编码规则 服务实现类
 * </p>
 *
 * @author wangxinghui
 * @since 2024-01-11
 */
@Service
public class MesCodeRulesServiceImpl extends ServiceImpl<MesCodeRulesMapper, MesCodeRules> implements MesCodeRulesService {
	
	@Resource
	protected RedisCache redisCache;
	
	
	@Override
	public String getCode(String key) {
		MesCodeRules rule = getRules(key);
		//自动生成编码长度是否达到最大值
		checkOverLength(rule);
		String code = null;
		if(StringUtils.isBlank(code)){
			if(StringUtils.isBlank(rule.getDefineRules())){
				return null;
			}
			code = rule.getHeadRule()+String.format("%0"+rule.getDigit()+"d",rule.getIncreasingNumber());
			setCode(key,code);
		}
		List<String> content = getContent(code);
		for(String con:content){
			code = getDate(code,con);
		}
		return code;
	}
	
	
	
	/**
	 * 更新序列号
	 *@return
	 */
	@Transactional(rollbackFor = BaseException.class)
	@Override
	public String updateCode(String key) {
		LambdaUpdateWrapper<MesCodeRules> wrapper = new LambdaUpdateWrapper<>();
		wrapper.eq(MesCodeRules::getBusinessType,key);
		MesCodeRules rule = getOne(wrapper);
		String code = getCode(key);
		//setCode("CODE:"+ key,rule.getRulesHead()+getSerialNumber2(rule.getRulesSerialNumber(),rule.getDigit()));
		rule.setIncreasingNumber(getAutoId(rule.getIncreasingNumber()).incrementAndGet());
		updateById(rule);
		return code;
	}
	
	
	@Override
	public String getHeadRule(String headRule) {
		String headRuleT = headRule+0;
		List<String> content = getContent(headRuleT);
		for(String con:content){
			headRuleT = getDate(headRuleT,con);
		}
		return headRuleT.substring(0,headRuleT.length()-1);
	}
	
	
	@Override
	public MesCodeRules getRules(String key) {
		LambdaUpdateWrapper<MesCodeRules> wrapper = new LambdaUpdateWrapper<>();
		wrapper.eq(MesCodeRules::getBusinessType,key);
		return getOne(wrapper);
	}
	
	
	
	@Override
	public void updateCodeByRepeat(String key,Integer serialNumber){
		MesCodeRules rules = getRules(key);
		rules.setIncreasingNumber(getAutoId(serialNumber).incrementAndGet());
		checkOverLength(rules);
		updateById(rules);
	}
	
	
	/**
	 * 检查编码是否自增到超过长度要求
	 */
	private void checkOverLength(MesCodeRules rules){
		Integer digit = rules.getDigit();
		String serialNumber = rules.getIncreasingNumber().toString();
		if(serialNumber.length() > digit){
			throw  new ServiceException("自动生成编码已达设置最大值！");
		}
	}
	
	
	
	
	/**
	 * 存储编码
	 * @return
	 */
	protected void setCode(String key,String value) {
		redisCache.setCacheObject(key,value);
	}
	
	
	
	/**
	 * 获取{}内容
	 * @param text
	 * @return
	 */
	protected List<String> getContent(String text){
		List<String> texts = new ArrayList<>();
		Pattern p = Pattern.compile("(\\{.+?\\})");
		Matcher m = p.matcher(text);
		while(m.find()) {
			texts.add(m.group(1));
		}
		return texts;
	}
	protected boolean checkContent(String content){
		if(StringUtils.isBlank(content)){
			return false;
		}
		String con = content.toLowerCase();
		if("p".equals(con)||"yyyy".equals(con)||"mm".equals(con)||"dd".equals(con)||con.matches("#+")){
			return true;
		}
		return false;
	}
	
	
	//编码转换
	protected String getDate(String code,String value){
		Calendar cal = Calendar.getInstance();
		String value2 = value.toLowerCase();
		if("{yyyy}".equals(value2)){
			code = code.replace(value,String.valueOf(cal.get(Calendar.YEAR)));
		}else if("{mm}".equals(value2)){
			code = code.replace(value,String.format("%02d",cal.get(Calendar.MONTH)+1));
		}else if("{dd}".equals(value2)){
			code = code.replace(value,String.format("%02d",cal.get(Calendar.DAY_OF_MONTH)));
		}else{
			code = code.replace(value,value.replace("{", "").replace("}", ""));
		}
		return code;
	}
	
	
	
	
	
	private AtomicInteger getAutoId(Integer serialNumber){
		 AtomicInteger ai = new AtomicInteger(serialNumber);
		 return ai;
	}
	
	
	
}
